﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Windows.Forms;

namespace WenSkin.Controls
{
    [ToolboxBitmap(typeof(DataGridView))]
    public class WenDataGridView : DataGridView
    {
        public event DataGridViewCellMouseEventHandler TextBoxButtonClick;
        public WenDataGridView()
        {
            base.SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.DoubleBuffer |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor, true);
            base.UpdateStyles();
            this.BackgroundColor = Color.FromArgb(37, 37, 38);
            this.ColumnHeadersHeight = 30;
            this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;

            //修改为默认选择整行
            this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            this.EnableHeadersVisualStyles = false;

            this.DefaultCellStyle = new DataGridViewCellStyle(this.DefaultCellStyle)
            {
                BackColor = Color.FromArgb(37, 37, 38),
                SelectionBackColor = Color.FromArgb(63, 63, 70)
            };
            this.RowHeadersDefaultCellStyle = new DataGridViewCellStyle(this.RowHeadersDefaultCellStyle)
            {
                BackColor = Color.FromArgb(37, 37, 38),
                SelectionBackColor = Color.FromArgb(63, 63, 70),
                ForeColor = Color.White,
            };
            this.ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle(this.RowHeadersDefaultCellStyle)
            {
                BackColor = Color.FromArgb(37, 37, 38),
                SelectionBackColor = Color.FromArgb(63, 63, 70),
                ForeColor = Color.White,
            };
        }

        #region 私有属性
        private TreeDataSourceNode treeDataSourceNode;
        private CheckBoxStateCollection checkedBoxs;
        private TreeDataGridViewRowNodeCollection nodes;
        private bool radioButtones;
        private bool checkBoxes;
        private int radioButtonRowIndex = -1;

        private StringFormat StringConters { get; set; }
                = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap)
                {
                    LineAlignment = StringAlignment.Center,
                    Alignment = StringAlignment.Center,
                    Trimming = StringTrimming.EllipsisCharacter
                };
        #endregion

        #region 公有属性
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Wen")]
        [Description("绑定数据节点信息设置")]
        public TreeDataSourceNode TreeDataSourceNode => treeDataSourceNode ??= new TreeDataSourceNode();

        [DefaultValue(10), Category("Wen"), Description("折叠按钮缩进值")]
        public int Indent { get; set; } = 10;

        [DefaultValue(false), Category("Wen"), Description("右键是否弹出筛选菜单")]
        public bool MouseButtonsRightFilterMenu { get; set; }

        [DefaultValue(false), Category("Wen"), Description("是否增加复选框")]
        public bool CheckBoxes { get => checkBoxes; set { checkBoxes = value; if (value) RadioButtones = false; } }

        [DefaultValue(false), Category("Wen"), Description("是否增加单选框")]
        public bool RadioButtones { get => radioButtones; set { radioButtones = value; if (value) CheckBoxes = false; } }

        [DefaultValue(null), Category("Wen"), Description("复选框集合")]
        [Browsable(false)]
        public CheckBoxStateCollection CheckedBoxs => checkedBoxs ??= new CheckBoxStateCollection(this);

        [DefaultValue(null), Category("Wen"), Description("单选框选择行")]
        [Browsable(false)]
        public int RadioButtonRowIndex { get => radioButtonRowIndex; }
        [DefaultValue(null), Category("Wen"), Description("节点数据")]
        [Browsable(false)]
        public TreeDataGridViewRowNodeCollection Nodes => nodes ??= new TreeDataGridViewRowNodeCollection();

        [DefaultValue(DataGridViewSelectionMode.FullRowSelect)]
        public new DataGridViewSelectionMode SelectionMode { get => base.SelectionMode; set => base.SelectionMode = value; }
        #endregion

        #region 委托

        public event DataGridViewRowCheckBoxEventHandler DataGridViewRowCheckBoxClick;

        public delegate void DataGridViewRowCheckBoxEventHandler(object sender, DataGridViewRowCheckBoxEventArgs e);

        public class DataGridViewRowCheckBoxEventArgs : EventArgs
        {
            private readonly int rowIndex;
            private readonly bool state;

            public DataGridViewRowCheckBoxEventArgs(int rowIndex, bool state)
            {
                this.rowIndex = rowIndex;
                this.state = state;
            }

            public int RowIndex => rowIndex;
            public bool State => state;

        }

        public virtual void OnTextBoxButtonClick(DataGridViewCellMouseEventArgs e)
        {
            TextBoxButtonClick?.Invoke(this, e);
        }

        //筛选委托
        public event WenDataGridViewFilterControl.WenDataGridViewFilterEventHandler WenDataGridViewFilter;

        public class DataGridViewRowItemClickEventArgs : EventArgs
        {
            public DataGridViewRowItemClickEventArgs(DataGridView dataGridView, DataGridViewCellMouseEventArgs e)
            {
                DataGridView = dataGridView;
                this.e = e;

                this.RowIndex = e.RowIndex;
                this.ColumnIndex = e.ColumnIndex;
                var data = dataGridView.Rows[RowIndex].DataBoundItem;
                DataGridViewRow = dataGridView.Rows[RowIndex];
                DataRow = data.GetType().GetProperty("Row").GetValue(data, null) as DataRow;      
            }

            public DataGridViewRow DataGridViewRow { get; private set; }
            public DataRow DataRow { get; private set; }
            public int RowIndex { get; private set; }
            public int ColumnIndex { get; private set; }
            public DataGridView DataGridView { get; private set; }
            public DataGridViewCellMouseEventArgs e { get; private set; }
        }
        public delegate void DataGridViewRowItemClickEventHandler(object sender, DataGridViewRowItemClickEventArgs e);
        public event DataGridViewRowItemClickEventHandler RowItemClick;

        #endregion

        #region 重绘

        //重绘外边框
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            g.SetGDIHigh();

            using Pen p = new Pen(Color.FromArgb(160, 160, 160));

            g.DrawRectangle(p, new Rectangle(0, 0, this.Width - 1, this.Height - 1));
        }

        //重绘每个单元格内容
        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {
            //base.OnCellPainting(e);
            Graphics g = e.Graphics.SetGDIHigh();
            Rectangle rec = e.CellBounds;
            using Brush bBack = new SolidBrush(e.CellStyle.BackColor);
            using Pen pen = new Pen(Color.FromArgb(160, 160, 160));
            //第一行第一列
            if (e.RowIndex == -1 && e.ColumnIndex == -1)
            {
                DrawBack(bBack, rec);
                string str = "序号";
                if (CheckBoxes || RadioButtones)
                    str = "选择";
                g.DrawString(str, e.CellStyle.Font, new SolidBrush(e.CellStyle.ForeColor), rec, StringConters);
            }
            //标题行
            else if (e.RowIndex == -1)
            {
                DrawBack(bBack, rec);
                DrawTitleRow();
            }
            //标题栏
            else if (e.ColumnIndex == -1)
            {
                if ((e.State & DataGridViewElementStates.Selected) != 0)
                {
                    DrawBack(new SolidBrush(Color.FromArgb(63, 63, 70)), rec);
                }
                else
                {
                    DrawBack(new SolidBrush(Color.FromArgb(37, 37, 38)), rec);
                }

                Rectangle recStr = rec;

                //增加复选框
                if (CheckBoxes || RadioButtones)
                {
                    int checkWidth = 15;
                    int checkY = (rec.Height - checkWidth) / 2 + rec.Y;
                    if (CheckBoxes)
                    {
                        if (CheckedBoxs[e.RowIndex].State)
                        {
                            CheckBoxRenderer.DrawCheckBox(g,
                                      new Point(rec.X, checkY),
                                      System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal);
                        }
                        else
                        {
                            CheckBoxRenderer.DrawCheckBox(g,
                                      new Point(rec.X, checkY),
                                      System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
                        }
                    }
                    if (RadioButtones)
                    {
                        //当前激活行
                        if (e.RowIndex == radioButtonRowIndex && this.CurrentCell.RowIndex == e.RowIndex)
                        {
                            RadioButtonRenderer.DrawRadioButton(g,
                                new Point(rec.X, checkY),
                                System.Windows.Forms.VisualStyles.RadioButtonState.CheckedNormal);
                        }
                        else
                        {
                            RadioButtonRenderer.DrawRadioButton(g,
                                 new Point(rec.X, checkY),
                                 System.Windows.Forms.VisualStyles.RadioButtonState.UncheckedNormal);
                        }
                    }
                    recStr = new Rectangle(rec.X + 17, rec.Y, rec.Width - 17 - rec.X, rec.Height);
                }
                //画序号
                g.DrawString((e.RowIndex + 1).ToString(), e.CellStyle.Font, new SolidBrush(e.CellStyle.ForeColor), recStr, WenSkin.Controls.ControlHelper.StringConters);
            }
            //画背景
            void DrawBack(Brush brush, Rectangle rec)
            {
                g.FillRectangle(brush, rec);
                //底部线条
                g.DrawLine(pen, rec.X, rec.Y + rec.Height - 1, rec.X + rec.Width - 1, rec.Y + rec.Height - 1);
                //单元格边上线条
                g.DrawLine(pen, rec.X + rec.Width - 1, rec.Y, rec.X + rec.Width - 1, rec.Y + rec.Height - 1);
                e.Handled = true;
                brush.Dispose();
            }

            void DrawTitleRow()
            {
                //画单元格内容
                Rectangle recString = new Rectangle(rec.X, rec.Y, rec.Width, rec.Height);
                Rectangle recImage = new Rectangle(rec.X + (rec.Width - 16), rec.Y + (rec.Height - 12) / 2, 12, 12);
                //文字水平垂直居中
                g.DrawString(e.Value?.ToString(), e.CellStyle.Font, new SolidBrush(ForeColor), recString, StringConters);

                if (FilterColumns.ContainsKey(this.Columns[e.ColumnIndex]))
                {
                    g.FillRectangle(new SolidBrush(this.BackgroundColor), new Rectangle(rec.X + (rec.Width - 18), rec.Y + (rec.Height - 16) / 2, 16, 16));
                    g.DrawImage(Properties.Resources.筛选, recImage);
                }
                else if (e.ColumnIndex == MouserMoveColumnIndex)
                {
                    g.FillRectangle(new SolidBrush(this.BackgroundColor), new Rectangle(rec.X + (rec.Width - 18), rec.Y + (rec.Height - 16) / 2, 16, 16));
                    g.DrawImage(Properties.Resources.三角形下, recImage);
                }
            }
        }

        #endregion

        #region 复选框问题处理

        public class CheckBoxState
        {
            public CheckBoxState(int rowIndex, bool state)
            {
                RowIndex = rowIndex;
                State = state;
            }

            public int RowIndex { get; set; }
            public bool State { get; set; }
        }
        public class CheckBoxStateCollection : WenSkin.Controls.WenCollection
        {
            private readonly WenDataGridView owner;
            public CheckBoxStateCollection(WenDataGridView owner)
            {
                this.owner = owner;
            }
            public WenDataGridView DataGridView => owner;
            public CheckBoxState this[int index]
            {
                get
                {
                    if (Items.ToArray().ToList().Find(a => (a as CheckBoxState).RowIndex == index) is CheckBoxState check)
                    {
                        return check;
                    }
                    else
                    {
                        CheckBoxState checkBoxState = new CheckBoxState(index, false);
                        Items.Add(checkBoxState);
                        return checkBoxState;
                    }
                }
            }
        }
        #endregion

        #region 鼠标点击事件
        
        protected override void OnCellMouseClick(DataGridViewCellMouseEventArgs e)
        {
            base.OnCellMouseClick(e);

            if (e.RowIndex == -1 && e.ColumnIndex > -1 && MouseButtonsRightFilterMenu)
            {
                Rectangle rec = this.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
                Rectangle recImage = new Rectangle(0 + (rec.Width - 18), 0 + (rec.Height - 16) / 2, 16, 16);
                if (recImage.Contains(e.Location) || e.Button == MouseButtons.Right)
                {
                    var fm = new WenDataGridViewFilterControl(this, this.Columns[e.ColumnIndex]);
                    fm.WenDataGridViewFilter += (s, e) =>
                    {
                        WenDataGridViewFilter?.Invoke(this, e);
                    };
                    fm.ShowDialog();
                }
            }

            if (e.RowIndex > -1)
            {
                radioButtonRowIndex = e.RowIndex;
                if (CheckedBoxs[e.RowIndex].State)
                {
                    CheckedBoxs[e.RowIndex].State = false;
                }
                else
                {
                    CheckedBoxs[e.RowIndex].State = true;
                }
                this.InvalidateRow(e.RowIndex);
                DataGridViewRowCheckBoxClick?.Invoke(this, new DataGridViewRowCheckBoxEventArgs(e.RowIndex, CheckedBoxs[e.RowIndex].State));
                RowItemClick?.Invoke(this, new DataGridViewRowItemClickEventArgs(this, e));
            }
        }

        #endregion

        #region 鼠标移动事件

        private int MouserMoveColumnIndex = -1;

        protected override void OnCellMouseMove(DataGridViewCellMouseEventArgs e)
        {
            base.OnCellMouseMove(e);
            if (e.RowIndex == -1)
            {
                if (MouserMoveColumnIndex == e.ColumnIndex)
                    return;
                this.Invalidate(this.GetCellDisplayRectangle(MouserMoveColumnIndex, -1, true));
                this.Invalidate(this.GetCellDisplayRectangle(e.ColumnIndex, -1, true));
                MouserMoveColumnIndex = e.ColumnIndex;
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            this.Invalidate(this.GetCellDisplayRectangle(MouserMoveColumnIndex, -1, true));
            MouserMoveColumnIndex = -1;
        }
        #endregion

        #region 筛选列数据记录

        public Dictionary<DataGridViewColumn, List<string>> FilterColumns = new Dictionary<DataGridViewColumn, List<string>>();

        //排序改变前后处理

        public void FilterWenDataGridViewRow()
        {
            //首先全部显示
            foreach (DataGridViewRow row in this.Rows)
            {
                row.Visible = true;
            }

            foreach (var item in FilterColumns)
            {
                foreach (DataGridViewRow row in this.Rows)
                {
                    if (row.IsNewRow || !row.Visible)
                        continue;

                    if (item.Value.Contains(row.Cells[item.Key.Index].Value?.ToString()))
                    {
                        row.Visible = false;
                    }
                }
            }
        }

        #endregion

        #region 排序改变事件
        protected override void OnSorted(EventArgs e)
        {
            base.OnSorted(e);
            FilterWenDataGridViewRow();
            CheckedBoxs.Clear();
            radioButtonRowIndex = -1;
        }
        #endregion

        #region 绑定数据

        private object dataSource { get; set; }
        public new object DataSource
        {
            get => dataSource;
            set
            {
                this.CheckedBoxs.Clear();
                radioButtonRowIndex = -1;
                this.FilterColumns.Clear();
                dataSource = value;
                if (TreeDataSourceNode.TreeDataSource)
                {
                    DataBind(value);
                }
                else
                {
                    base.DataSource = value;
                    //不允许排序功能
                    foreach (DataGridViewColumn item in base.Columns)
                    {
                        item.SortMode = DataGridViewColumnSortMode.NotSortable;
                    }
                }
            }
        }
        private void DataBind(object value)
        {
            if (value == null)
                return;

            //tree模式不允许排序功能
            foreach (DataGridViewColumn item in base.Columns)
            {
                item.SortMode = DataGridViewColumnSortMode.NotSortable;
            }

            if (value is DataSet ds)
            {
                DataBind(ds.Tables[0]);
            }
            else if (value is DataTable dt)
            {
                DataBind(dt);
            }

            void DataBind(DataTable dt)
            {
                this.Nodes.Clear();
                this.Rows.Clear();
                //判定是否是数据绑定输结构模式
                DataBindTreeNode(dt, this.Nodes, null, TreeDataSourceNode.RootContent, 0, Indent, "");
            }
        }

        #endregion

        #region 绑定节点

        private TreeDataGridViewRowNodeCollection DataBindTreeNode(DataTable dt, TreeDataGridViewRowNodeCollection nodes,
            DataGridViewRow parentLevel
            , string value, int level, int indent, string paternelnodePath)
        {
            DataRow[] rows = dt.Select($"{TreeDataSourceNode.ParentNode}=\'{value}\'");
            int index = 0;
            foreach (var item in rows)
            {
                int indexRow = this.Rows.Add();
                DataGridViewRow dataGridViewRow = Rows[indexRow];

                TreeDataGridViewCellValues treeData = new TreeDataGridViewCellValues();
                string nodePath = paternelnodePath + "/" + index++;
                TreeDataGridViewRowNode node = new TreeDataGridViewRowNode(this)
                {
                    ParentLevel = parentLevel,
                    DataGridViewRow = dataGridViewRow,
                };


                string parentValue = string.Empty;
                if (item is DataRow row)
                {
                    parentValue = row[TreeDataSourceNode.ChildNode]?.ToString();
                    foreach (DataGridViewColumn column in base.Columns)
                    {
                        DataGridViewCell cell = column.CellTemplate;

                        if (cell is WenTreeDataGridViewTextBoxCell)
                        {
                            treeData = new TreeDataGridViewCellValues()
                            {
                                Text = row[column.DataPropertyName]?.ToString(),
                                Level = level,
                                Indent = indent,
                                NodePath = nodePath,
                            };
                            dataGridViewRow.Cells[column.Name].Value = treeData;
                        }
                        else
                        {
                            dataGridViewRow.Cells[column.Name].Value = row.Table.Columns.Contains(column.DataPropertyName) ? row[column.DataPropertyName] : null;
                        }
                    }
                }

                nodes.Add(node);
                var subnodes = DataBindTreeNode(dt, node.Nodes, dataGridViewRow, parentValue, level + 1, indent, nodePath);
                treeData.Nodes.AddRange(subnodes);
                treeData.TreeDataGridViewRowNode = node;
                node.Nodes.AddRange(subnodes);
            }
            return nodes;
        }

        #endregion
    }

}
